﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;

using Storm;
using Storm.Docking;
using Storm.Docking.Controls;
using Storm.Docking.Visual;
using Storm.Docking.Visual.Drawing;

namespace Storm.Docking.Visual.Glyphs
{
    /// <summary>
    /// Represents a base class for all DockCaption glyphs to 
    /// inherit from.
    /// </summary>
    public class Glyph
        : Panel
    {
        #region Fields

        // Design members.
        private TransImage image = null;

        // Basic members.
        private bool isMouseOver = false;
        private bool isMouseClicked = false;
        private Rectangle glyphRect = Rectangle.Empty;
        private DockCaption dockCaption = null;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets whether the cursor is over the Glyph.
        /// </summary>
        [Browsable(false)]
        [Description("Gets or sets whether the cursor is over the Glyph.")]
        public bool IsMouseOver
        {
            get { return this.isMouseOver; }
            set
            {
                this.isMouseOver = value;
                this.Invalidate();  // Call Invalidate to redraw.
            }
        }

        /// <summary>
        /// Gets or sets whether the mouse is clicked on the Glyph.
        /// </summary>
        [Browsable(false)]
        [Description("Gets or sets whether the mouse is clicked on the Glyph.")]
        public bool IsMouseClicked
        {
            get { return isMouseClicked; }
            set
            {
                isMouseClicked = value;
                this.Invalidate();  // Call Invalidate to redraw.
            }
        }

        /// <summary>
        /// Gets or sets the Rectangle Bounds of the Glyph.
        /// </summary>
        [Browsable(false)]
        [Description("Gets or sets the Rectangle Bounds of the Glyph.")]
        public new Rectangle Bounds
        {
            get { return this.glyphRect; }
            set { this.glyphRect = value; }
        }

        /// <summary>
        /// Gets or sets the DockCaption parent of the Glyph.
        /// </summary>
        [Browsable(true)]
        [Description("Gets or sets the DockCaption parent of the Glyph.")]
        public DockCaption DockCaption
        {
            get { return this.dockCaption; }
            set
            {
                this.dockCaption = value;
                this.UpdateGlyphDesign();
            }
        }

        /// <summary>
        /// Gets or sets the TransImage control of the Glyph.
        /// </summary>
        [Browsable(false)]
        [Description("Gets or sets the TransImage control of the Glyph.")]
        public TransImage Image
        {
            get { return image; }
            set { image = value; }
        }

        /// <summary>
        /// Gets the Glyph's hovering Bounds.
        /// </summary>
        [Browsable(false)]
        [Description("Gets the Glyph's hovering Bounds.")]
        public Rectangle GlyphRect
        { get { return glyphRect; } }

        #endregion

        #region Methods

        #region Public

        /// <summary>
        /// Updates the design of the Glyph to match the DockCaption's design.
        /// </summary>
        public void UpdateGlyphDesign()
        {
            // Initialize the base settings.
            this.AutoSize = false;
            this.BackColor = Color.Transparent;
            this.Dock = DockStyle.Right;
            this.Visible = true;

            // Initialize our hovering Bounds..
            glyphRect = new Rectangle(this.Location.X + 1,
                                       this.Location.Y + 2,
                                       14, 14);

            // Set the Bounds of the CloseGlyph.
            this.Width = this.GlyphRect.Width + 2;
            this.Height = this.GlyphRect.Height + 2;

            this.Image.Location = new Point(this.GlyphRect.Location.X,
                                             this.GlyphRect.Location.Y);
        }

        #endregion

        #region Private

        private void OnImageDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                this.IsMouseClicked = true;
        }

        private void OnImageUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                this.IsMouseClicked = false;
        }

        private void OnImageEnter(object sender, EventArgs e)
        { this.IsMouseOver = true; }

        private void OnImageLeave(object sender, EventArgs e)
        { this.IsMouseOver = false; }

        private void OnImageClick(object sender, EventArgs e)
        {
            this.DockCaption.Focus();
            this.OnClickAction();
        }

        #endregion

        #region Internal

        /// <summary>
        /// Draws the Glyph's border depending on the DockCapton's
        /// focus state and whether the mouse is hovering over 
        /// the Glyph.
        /// </summary>
        /// <param name="g">Graphics that the Glyph should use to draw itself.</param>
        internal void DrawGlyph(Graphics g)
        {
            if (this.IsMouseOver == true)
            {
                if (this.IsMouseClicked == true)
                    this.DockCaption.Renderer.GlyphDrawPressed(this, g);
                else
					this.DockCaption.Renderer.GlyphDrawHover(this, g);
            }
        }

        /// <summary>
        /// Made to be overridden by inheriters.
        /// </summary>
        internal virtual void OnClickAction()
        {
        }

        /// <summary>
        /// Made to be overridden by inheriters.
        /// </summary>
        internal virtual void OnParentRecieveFocus
            (object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Made to be overridden by inheriters.
        /// </summary>
        internal virtual void OnParentReleaseFocus
            (object sender, EventArgs e)
        {
        }

        #endregion

        #region Protected

        protected override void OnClick(EventArgs e)
        {
            this.DockCaption.Focus();
            this.OnClickAction();

            base.OnClick(e);
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            this.IsMouseOver = true;
            base.OnMouseEnter(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            this.IsMouseOver = false;
            base.OnMouseLeave(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                this.IsMouseClicked = true;

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                this.IsMouseClicked = false;

            base.OnMouseUp(e);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            this.DrawGlyph(e.Graphics);
            base.OnPaint(e);
        }

        #endregion

        #endregion

		/// <summary>
		/// Initializes a new instance of the <see cref="Glyph"/> class.
		/// </summary>
		/// <param name="parent">The parent.</param>
        public Glyph(DockCaption parent)
        {
            // Prevent parent from being null.
            if (parent == null) throw new ArgumentNullException("parent");

            // Update our DockCaption parent to match what's
            // specified in the arguments.

            dockCaption = parent;

            // Add the DockCaption's EventHandlers.
            this.DockCaption.RecieveFocus += OnParentRecieveFocus;
            this.DockCaption.ReleaseFocus += OnParentReleaseFocus;

            // Initialize the base TransImage.
            this.Image = new TransImage(null);
            this.Controls.Add(this.Image);

            // Update the Glyph's design.
            this.UpdateGlyphDesign();

            // EventHandlers.
            this.Image.MouseEnter += OnImageEnter;
            this.Image.MouseLeave += OnImageLeave;
            this.Image.MouseDown += OnImageDown;
            this.Image.MouseUp += OnImageUp;
            this.Image.Click += OnImageClick;

            // Set styles to prevent flickering.
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);

            // Should not be allowed to select this control.
            this.SetStyle(ControlStyles.Selectable, true);
        }
    }
}
